home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 108_01 / rtfiles.c < prev    next >
Text File  |  1985-11-13  |  12KB  |  547 lines

  1. /*
  2.     RT-11 Adapter Package for CP/M
  3.  
  4.     Rev. 1.0 -- July 1980
  5.  
  6.     Rev. 1.1 -- March 1981 consisting of adding a valid system date
  7.             word to all files placed on the RT-11 disk and
  8.             putting the volume ID on a disk when the directory
  9.             is initialized.  This will keep RT-11 versions
  10.             later than V02C from choking.
  11.  
  12.     copyright (c) 1980, William C. Colley, III
  13.  
  14. This group of functions implements enough of RT-11 to allow the rest of
  15. the package to work.  The functions are built and named as per the
  16. RT-11 Software Support Manual for version 2C of RT-11.
  17. */
  18.  
  19. #include "RT11.H"
  20.  
  21. /*
  22. Routine to look up an RT-11 file.  The routine accepts a file name as an
  23. array of int and returns 0 if the file was not found, 1 otherwise.
  24. The length of the file can be extracted thru dir_pointer, and the
  25. starting block of the file appears in file_start.
  26. */
  27.  
  28. lookup(file_name)
  29. int *file_name;
  30. {
  31.     usrcom();
  32.     return dleet(file_name);
  33. }
  34.  
  35. /*
  36. Routine to rename an RT-11 file.  Pass the old and new names.  The routine
  37. returns 0 if the file doesn't exist, 1 otherwise.
  38. */
  39.  
  40. rename(old_file,new_file)
  41. int *old_file, *new_file;
  42. {
  43.     char i;
  44.     usrcom();
  45.     if (!dleet(old_file)) return 0;
  46.     for (i = 0; i < 3; i++) _putword(dir_pointer,i+1,new_file[i]);
  47.     *dir_pointer = 0;
  48.     *(dir_pointer + 1) = TENTAT;
  49.     clocom(new_file);
  50.     return 1;
  51. }
  52.  
  53. /*
  54. Routine to delete an RT-11 file.  Pass the routine the file name as an
  55. array of int.  If the file does not exist, the routine returns 0, else
  56. it returns 1.
  57. */
  58.  
  59. delete(file_name)
  60. int *file_name;
  61. {
  62.     usrcom();
  63.     if (!dleet(file_name)) return 0;
  64.     *dir_pointer = 0;
  65.     *(dir_pointer + 1) = EMPTY;
  66.     consol(0);
  67.     segrw(WRITE,current_segment);
  68.     return 1;
  69. }
  70.  
  71. /*
  72. Routine to build a tentative entry in the directory.  Routine requires
  73. a file name in an array of int, and the size of the file required.  The
  74. routine returns 0 if the entry is not possible, or the first block of
  75. the file if it is.  If the entry fails, the appropriate diagnostic is printed.
  76. */
  77.  
  78. enter(file_name,size)
  79. int *file_name, size;
  80. {
  81.     char *save_pntr, i;
  82.     unsigned ret_value;
  83.     usrcom();
  84.     do
  85.     {
  86. retry:        consol(0);
  87.         while (entry(EMPTY))
  88.         {
  89.             if (size <= _getword(dir_pointer,4))
  90.             {
  91.                 save_pntr = dir_pointer;
  92.                 ret_value = file_start;
  93.                 while (entry(EMPTY)) incr1();
  94.                 if (dir_pointer > &directory.entries[1000] -
  95.                     directory.extra_bytes)
  96.                 {
  97.                     ret_value = current_segment;
  98.                     if (extend())
  99.                     {
  100.                         blkchk(ret_value);
  101.                         goto retry;
  102.                     }
  103.                     puts("\nError -- directory full\n");
  104.                     return 0;
  105.                 }
  106.                 dir_pointer = save_pntr;
  107.                 _expand(dir_pointer);
  108.                 *dir_pointer++ = 0;
  109.                 *dir_pointer++ = TENTAT;
  110.                 for (i = 0; i < 3; i++)
  111.                 {
  112.                     _putword(dir_pointer,i,file_name[i]);
  113.                 }
  114.                 _putword(dir_pointer,3,size);
  115.                 _putword(dir_pointer,5,sysdate);
  116.                 incr1();
  117.                 _putword(dir_pointer,3,
  118.                     _getword(dir_pointer,3) - size);
  119.                 segrw(WRITE,current_segment);
  120.                 return ret_value;
  121.             }
  122.             incr1();
  123.         }
  124.     }
  125.     while (nxblk());
  126.     puts("\nError -- no large enough gaps\n");
  127.     return 0;
  128. }
  129.  
  130. /*
  131. Routine to extend an RT-11 directory by splitting a directory segment.
  132. The routine returns 0 if no directory segment is available, 1 otherwise.
  133. */
  134.  
  135. extend()
  136. {
  137.     struct dirseg temp_seg;
  138.     int t, newseg;
  139.     emt_375(READ,0,2,temp_seg);
  140.     if (temp_seg.highest_segment >= temp_seg.total_segments) return 0;
  141.     newseg = temp_seg.highest_segment;
  142.     temp_seg.highest_segment++;
  143.     emt_375(WRITE,0,2,temp_seg);
  144.     movmem(directory,temp_seg,1024);
  145.     blkchk(current_segment);
  146.     for (t = (1024 - 10) / (14 + directory.extra_bytes);
  147.         t > 0; t--) incr1();
  148.     *dir_pointer = 0;
  149.     *(dir_pointer + 1) = EMPTY;
  150.     temp_seg.next_segment = directory.next_segment;
  151.     directory.next_segment = newseg;
  152.     segrw(WRITE,current_segment);
  153.     temp_seg.first_block = file_start;
  154.     movmem(temp_seg,directory,10);
  155.     movmem(temp_seg.entries + (dir_pointer - directory.entries),
  156.         directory.entries, directory.entries + 1024 - dir_pointer);
  157.     segrw(WRITE,newseg);
  158.     current_segment = newseg;
  159.     blkchk(newseg);
  160.     return 1;
  161. }
  162.  
  163. /*
  164. Routine to close an RT-11 file.  The file name comes over in radix 50 in
  165. the array file_name.  The routine returns 0 if no file by that name was
  166. around to close, 1 otherwise.
  167. */
  168.  
  169. klose(file_name)
  170. int *file_name;
  171. {
  172.     char i;
  173.     blkchk(1);
  174.     do
  175.     {
  176.         while(entry(TENTAT))
  177.         {
  178.             for (i = 0; i < 3; i++)
  179.             {
  180.                 if (_getword(dir_pointer,i+1) !=
  181.                     file_name[i]) break;
  182.             }
  183.             if (i == 3)
  184.             {
  185.                 clocom(file_name);
  186.                 return 1;
  187.             }
  188.             incr1();
  189.         }
  190.     }
  191.     while (nxblk());
  192.     return 0;
  193. }
  194.     
  195. /*
  196. Routine that continues close and rename operations.
  197. */
  198.  
  199. clocom(file_name)
  200. int *file_name;
  201. {
  202.     char *tdptr;
  203.     int tseg;
  204.     tdptr = dir_pointer;
  205.     tseg = current_segment;
  206.     if (dleet(file_name))
  207.     {
  208.         *dir_pointer = 0;
  209.         *(dir_pointer + 1) = EMPTY;
  210.         if (tseg != current_segment)
  211.         {
  212.             consol(0);
  213.             segrw(WRITE,current_segment);
  214.         }
  215.     }
  216.     blkchk(tseg);
  217.     dir_pointer = tdptr;
  218.     *tdptr++ = 0;
  219.     *tdptr = PERM;
  220.     consol(0);
  221.     segrw(WRITE,current_segment);
  222. }    
  223.  
  224. /*
  225. Routine to get an RT-11 file name from the console.  The name is packed
  226. into the int array file_name in radix 50.  The routine returns 0
  227. if the file name is not legal, 1 otherwise.
  228. */
  229.  
  230. getfd(file_name)
  231. int *file_name;
  232. {
  233.     char c, i, j, name[20], *pntr;
  234.     pntr = gets(name);
  235.     file_name[0] = file_name[1] = file_name[2] = 0;
  236.     for (i = 0; i < 2; i++)
  237.     {
  238.         for (j = 0; j < 3; j++)
  239.         {
  240.             c = *pntr;
  241.             if (c == '.' || c == '\0') c = ' ';
  242.             else pntr++;
  243.             if ((c = ator50(c)) == 255) return 0;
  244.             file_name[i] = file_name[i] * 050 + c;
  245.         }
  246.     }
  247.     if (*pntr == '.') pntr++;
  248.     for (i = 0; i < 3; i++)
  249.     {
  250.         c = *pntr;
  251.         if (c == '\0') c = ' ';
  252.         else pntr++;
  253.         if ((c = ator50(c)) == 255) return 0;
  254.         file_name[2] = file_name[2] * 050 + c;
  255.     }
  256.     return 1;
  257. }
  258.  
  259. /*
  260. Routine to set up an RT-11 file I/O operation.
  261. */
  262.  
  263. usrcom()
  264. {
  265.     current_segment = 0;
  266.     blkchk(1);
  267. }
  268.  
  269. /*
  270. Routine to scan the directory for a file of a specified name.  The routine
  271. is passed the file name in radix 50 as an array of int.  The routine returns
  272. 0 if the file is not found, 1 otherwise.
  273. */
  274.  
  275. dleet(file_name)
  276. int *file_name;
  277. {
  278.     char i;
  279.     blkchk(1);
  280.     do
  281.     {
  282.         while(entry(PERM))
  283.         {
  284.             for (i = 0; i < 3; i++)
  285.             {
  286.                 if (_getword(dir_pointer,i+1) !=
  287.                     file_name[i]) break;
  288.             }
  289.             if (i == 3) return 1;
  290.             incr1();
  291.         }
  292.     }
  293.     while (nxblk());
  294.     return 0;
  295. }
  296.  
  297. /*
  298. Routine to get the next directory segment into core.  The routine returns
  299. 0 if no next segment exists, 1 otherwise.
  300. */
  301.  
  302. nxblk()
  303. {
  304.     if (directory.next_segment == 0) return 0;
  305.     blkchk(directory.next_segment);
  306.     return 1;
  307. }
  308.  
  309. /*
  310. Routine to find out if the requested directory segment is in core.  If it
  311. isn't, the segment is read in.
  312. */
  313.  
  314. blkchk(segment)
  315. int segment;
  316. {
  317.     if (segment != current_segment)
  318.     {
  319.         current_segment = segment;
  320.         segrw(READ,segment);
  321.     }
  322.     dir_pointer = directory.entries;
  323.     file_start = directory.first_block;
  324. }
  325.  
  326. /*
  327. Function to read/write a directory segment.  Parameters passed are the
  328. directory segment desired, and a read/write flag as per emt_375.
  329. */
  330.  
  331. segrw(read_write,segment)
  332. int segment;
  333. char read_write;
  334. {
  335.     emt_375(read_write,segment * 2 + 4,2,directory);
  336. }
  337.  
  338. /*
  339. Routine to find a specified file type in a directory segment.
  340. The routine starts from the current value of dir_pointer, and
  341. returns either 0 if the type isn't found or 1 if it is.
  342. */
  343.  
  344. entry(type)
  345. char type;
  346. {
  347.     char t;
  348.     while (1)
  349.     {
  350.         if ((t = *(dir_pointer + 1)) == type) return 1;
  351.         if (t == ENDSEG) return 0;
  352.         incr1();
  353.     }
  354. }
  355.  
  356. /*
  357. Routine to increment the directory pointer to the next entry in the
  358. directory.
  359. */
  360.  
  361. incr1()
  362. {
  363.     file_start += _getword(dir_pointer,4);
  364.     dir_pointer += 14 + directory.extra_bytes;
  365. }
  366.  
  367. /*
  368. Routine to compress the stray tentatives and empties out of a directory
  369. segment.  The file name file_name gives a tentative file that is to be
  370. exempt from the compression (i. e., there is only one active channel).
  371. If no files are to be exempt, pass 0 for file_name.
  372. */
  373.  
  374. consol(file_name)
  375. int *file_name;
  376. {
  377.     char